/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ia1_practica3;

import java.util.HashMap;
import java.util.ArrayList;

/**
 *
 * @author Edson Salazar
 */
public class Matriz {

    private Casilla[][] Matriz;
    private int ancho = 25;
    private int alto = 17;
    HashMap<Integer, Casilla> posiblesMov;
    ArrayList<NodoHoja> posiblesMovpunteo;
    /**
     * Lista de Fichas player 1
     */
    private ArrayList<Casilla> listaFichas1;
    /**
     * Lista de Fichas Player 2
     */
    private ArrayList<Casilla> listaFichas2;

    public Matriz() {
        listaFichas1 = new ArrayList<Casilla>();
        listaFichas2 = new ArrayList<Casilla>();
        Matriz = new Casilla[ancho][alto];
        inicializarMatriz();
    }

    public Matriz(int ancho, int alto) {
        this.ancho = ancho;
        this.alto = alto;
        Matriz = new Casilla[ancho][alto];
        inicializarMatriz();

    }

    public int getAlto() {
        return alto;
    }

    public void setAlto(int alto) {
        this.alto = alto;
    }

    public int getAncho() {
        return ancho;
    }

    public void setAncho(int ancho) {
        this.ancho = ancho;
    }

    public ArrayList<Casilla> getListaFichas1() {
        return listaFichas1;
    }

    public ArrayList<Casilla> getListaFichas2() {
        return listaFichas2;
    }

    private void inicializarMatriz() {
        posiblesMov = new HashMap<Integer, Casilla>();
        posiblesMovpunteo = new ArrayList<NodoHoja>();
        Casilla temp;
        //Llenando casillas del oponente
        int limizq = ancho / 2;
        int limder = ancho / 2;
        int limver = alto / 4;
        for (int i = 0; i < limver; i++) {
            for (int j = limizq; j <= limder; j = j + 2) {
                temp = new Casilla(Casilla.EST_JUGADOR2, j, i);
                Matriz[j][i] = temp;
                listaFichas2.add(temp);
            }
            limizq--;
            limder++;
        }
        //Llenando casillas vacias
        limizq = 0;
        limder = ancho - 1;
        limver = 3 * alto / 4 + 1;
        for (int i = alto / 4; i < limver; i++) {
            for (int j = limizq; j <= limder; j = j + 2) {
                Matriz[j][i] = new Casilla(Casilla.EST_VACIA, j, i);
                //System.out.print("Pos(x,y): ("+j+", "+i+");");
            }
            if (i < (alto / 2)) {
                limder--;
                limizq++;
                //System.out.println("   Disminuyendo="+(alto/2));
            } else {
                limder++;
                limizq--;
                //System.out.println("   Aumentando="+(alto/2));
            }
        }
        //Llenando casillas del jugador
        limizq = ancho / 2 - (ancho / 8);
        limder = ancho / 2 + (ancho / 8);
        for (int i = 3 * alto / 4 + 1; i < alto; i++) {
            for (int j = limizq; j <= limder; j = j + 2) {
                temp = new Casilla(Casilla.EST_JUGADOR1, j, i);
                Matriz[j][i] = temp;
                listaFichas1.add(temp);
            }
            limizq++;
            limder--;
        }
    }

    public Casilla getCasilla(int columna, int fila) {
//        Casilla izq = Matriz[columna==0 ? columna : columna--][fila];
//        Casilla der = Matriz[columna==(ancho-1) ? columna : columna++][fila];
//        if((izq==null || der==null) && Matriz[columna][fila]==null ){
//            return new Casilla(10);
//        }
        return Matriz[columna][fila] == null ? new Casilla(10, columna, fila) : Matriz[columna][fila];
    }

    public HashMap<Integer, Casilla> getPosiblesMov(int columna, int fila) {
        posiblesMov.clear();
        posiblesMovpunteo = new ArrayList<NodoHoja>();
        //Verificando casillas adyacentes (izquierda y derecha)
        Casilla temp;
        if (Matriz[columna][fila] != null) {
            if ((temp = this.getCasillaIzq(columna, fila)) != null) {
                if (temp.getTipoCasilla() == 0 || temp.getTipoCasilla() == 1) {
                    posiblesMov.put(getClave(temp), temp);
                    posiblesMovpunteo.add(new NodoHoja(2, temp, columna - 2, fila));
                } else {
                    posiblesMov = getsaltosIzq(1, columna - 2, fila, temp, posiblesMov);
                }
            }
            if ((temp = this.getCasillaDer(columna, fila)) != null) {
                if (temp.getTipoCasilla() == 0 || temp.getTipoCasilla() == 1) {
                    posiblesMov.put(getClave(temp), temp);
                    posiblesMovpunteo.add(new NodoHoja(2, temp, columna - 2, fila));
                } else {
                    posiblesMov = getsaltosDerecha(2, columna + 2, fila, temp, posiblesMov);
                }

            }
            if ((temp = this.getCasillaIzqAbajo(columna, fila)) != null) {
                if (temp.getTipoCasilla() == 0 || temp.getTipoCasilla() == 1) {
                    posiblesMov.put(getClave(temp), temp);
                    posiblesMovpunteo.add(new NodoHoja(3, temp, columna - 1, fila + 1));
                } else {
                    posiblesMov = getsaltosAbajoIzq(2, columna - 1, fila + 1, temp, posiblesMov);
                }
            }
            if ((temp = this.getCasillaIzqArriba(columna, fila)) != null) {
                if (temp.getTipoCasilla() == 0 || temp.getTipoCasilla() == 1) {
                    posiblesMov.put(getClave(temp), temp);
                    posiblesMovpunteo.add(new NodoHoja(3, temp, columna - 1, fila - 1));
                } else {
                    posiblesMov = getsaltosArrIzq(2, columna - 1, fila - 1, temp, posiblesMov);
                }
            }
            if ((temp = this.getCasillaDerAbajo(columna, fila)) != null) {
                if (temp.getTipoCasilla() == 0 || temp.getTipoCasilla() == 1) {
                    posiblesMovpunteo.add(new NodoHoja(3, temp, columna + 1, fila + 1));
                    posiblesMov.put(getClave(temp), temp);
                } else {
                    posiblesMov = getsaltosAbajoDerecha(3, columna + 1, fila + 1, temp, posiblesMov);
                }
            }
            if ((temp = this.getCasillaDerArriba(columna, fila)) != null) {
                if (temp.getTipoCasilla() == 0 || temp.getTipoCasilla() == 1) {
                    posiblesMovpunteo.add(new NodoHoja(3, temp, columna + 1, fila - 1));
                    posiblesMov.put(getClave(temp), temp);
                } else {
                    posiblesMov = getsaltosArrDerecha(3, columna + 1, fila - 1, temp, posiblesMov);

                }
            }
        }
        return this.posiblesMov;
    }

    public HashMap<Integer, Casilla> getsaltosArrDerecha(int tiposalto, int columnaux, int fila, Casilla temp, HashMap<Integer, Casilla> posiblesMov2) {
        Casilla temp2;
        int saltos = 1;
        while (temp != null) {
            System.out.println("-*-*-**//*" + columnaux + "--" + fila);
            if ((temp2 = this.getCasillaDerArriba(columnaux, fila)) != null) {
                if (temp2.getTipoCasilla() == 0 || temp2.getTipoCasilla() == 1) {
                    int punteo = saltos * 5;
                    if (columnaux > 17 || columnaux < 8) {
                        punteo -= saltos * 2;
                    }
                    posiblesMovpunteo.add(new NodoHoja(punteo, temp2, columnaux, fila));
                    saltos++;
                    posiblesMov2.put(getClave(temp2), temp2);

                    columnaux += 2;
                    fila -= 2;
                    if (columnaux < 0) {
                        columnaux = 0;
                        temp = null;
                        break;
                    } else if (fila < 0) {
                        fila = 0;
                        temp = null;
                        break;
                    } else {
                        if (Matriz[columnaux][fila].getTipoCasilla() > 1 && Matriz[columnaux][fila].getTipoCasilla() < 5) {
                            temp = temp2;
                        } else {
                            temp = null;
                        }
                    }
                } else {
                    temp = null;
                }
            } else {
                temp = null;
            }
        }
        return posiblesMov2;
    }

    public HashMap<Integer, Casilla> getsaltosAbajoDerecha(int tiposalto, int columnaux, int fila, Casilla temp, HashMap<Integer, Casilla> posiblesMov2) {
        Casilla temp2;
        int saltos = 1;
        while (temp != null) {
            System.out.println("-*-*-*--¡¡**" + columnaux + "--" + fila);
            if ((temp2 = this.getCasillaDerAbajo(columnaux, fila)) != null) {
                if (temp2.getTipoCasilla() == 0 || temp2.getTipoCasilla() == 1) {
                    int punteo = saltos * 5;
                    if (columnaux > 17 || columnaux < 8) {
                        punteo -= saltos * 2;
                    }
                    posiblesMovpunteo.add(new NodoHoja(punteo, temp2, columnaux, fila));
                    saltos++;
                    posiblesMov2.put(getClave(temp2), temp2);
                    columnaux += 2;
                    fila += 2;
                    if (columnaux < 0) {
                        columnaux = 0;
                        temp = null;
                        break;
                    } else if (fila > 24) {
                        fila = 24;
                        temp = null;
                        break;
                    } else {
                        if (Matriz[columnaux][fila].getTipoCasilla() > 1 && Matriz[columnaux][fila].getTipoCasilla() < 5) {
                            temp = temp2;
                        } else {
                            temp = null;
                        }
                    }
                } else {
                    temp = null;
                }
            } else {
                temp = null;
            }
        }
        return posiblesMov2;
    }

    public HashMap<Integer, Casilla> getsaltosAbajoIzq(int tiposalto, int columnaux, int fila, Casilla temp, HashMap<Integer, Casilla> posiblesMov2) {
        Casilla temp2;
        int saltos = 0;
        while (temp != null) {
            System.out.println("-*-*-*??**" + columnaux + "--" + fila);
            if ((temp2 = this.getCasillaIzqAbajo(columnaux, fila)) != null) {
                if (temp2.getTipoCasilla() == 0 || temp2.getTipoCasilla() == 1) {
                    int punteo = saltos * 5;
                    if (columnaux > 17 || columnaux < 8) {
                        punteo -= saltos * 2;
                    }
                    posiblesMovpunteo.add(new NodoHoja(punteo, temp2, columnaux, fila));
                    saltos++;
                    posiblesMov2.put(getClave(temp2), temp2);
                    columnaux -= 2;
                    fila += 2;
                    if (columnaux < 0) {
                        columnaux = 0;
                        temp = null;
                        break;
                    } else if (fila > 24) {
                        fila = 24;
                        temp = null;
                        break;
                    } else {
                        if (Matriz[columnaux][fila].getTipoCasilla() > 1 && Matriz[columnaux][fila].getTipoCasilla() < 5) {
                            temp = temp2;
                        } else {
                            temp = null;
                        }
                    }
                } else {
                    temp = null;
                }
            } else {
                temp = null;
            }
        }
        return posiblesMov2;
    }

    public HashMap<Integer, Casilla> getsaltosArrIzq(int tiposalto, int columnaux, int fila, Casilla temp, HashMap<Integer, Casilla> posiblesMov2) {
        Casilla temp2;
        int saltos = 1;
        while (temp != null) {
            System.out.println("-*-*-**%%%*" + columnaux + "--" + fila);
            if ((temp2 = this.getCasillaIzqArriba(columnaux, fila)) != null) {
                if (temp2.getTipoCasilla() == 0 || temp2.getTipoCasilla() == 1) {
                    int punteo = saltos * 5;
                    if (columnaux > 17 || columnaux < 8) {
                        punteo -= saltos * 2;
                    }
                    posiblesMovpunteo.add(new NodoHoja(punteo, temp2, columnaux, fila));
                    saltos++;
                    posiblesMov2.put(getClave(temp2), temp2);
                    columnaux -= 2;
                    fila -= 2;
                    if (columnaux < 0) {
                        columnaux = 0;
                        temp = null;
                        break;
                    } else if (fila < 0) {
                        fila = 0;
                        temp = null;
                        break;
                    } else {
                        if (Matriz[columnaux][fila].getTipoCasilla() > 1 && Matriz[columnaux][fila].getTipoCasilla() < 5) {
                            temp = temp2;
                        } else {
                            temp = null;
                        }
                    }
                } else {
                    temp = null;
                }
            } else {
                temp = null;
            }
        }
        return posiblesMov2;
    }

    public HashMap<Integer, Casilla> getsaltosDerecha(int tiposalto, int columnaux, int fila, Casilla temp, HashMap<Integer, Casilla> posiblesMov2) {
        Casilla temp2;
        int saltos = 1;
        while (temp != null) {
            System.out.println("-*-*-**==*" + columnaux + "--" + fila);
            if ((temp2 = this.getCasillaDer(columnaux, fila)) != null) {
                if (temp2.getTipoCasilla() == 0 || temp2.getTipoCasilla() == 1) {
                    int punteo = saltos * 4;
                    if (columnaux > 17 || columnaux < 8) {
                        punteo -= saltos * 2;
                    }
                    posiblesMovpunteo.add(new NodoHoja(punteo, temp2, columnaux, fila));
                    saltos++;
                    posiblesMov2.put(getClave(temp2), temp2);
                    columnaux += 4;
                    if (columnaux < 0) {
                        columnaux = 0;
                        temp = null;
                        break;
                    } else {

                        if (Matriz[columnaux][fila] != null && Matriz[columnaux][fila].getTipoCasilla() > 1 && Matriz[columnaux][fila].getTipoCasilla() < 5) {
                            temp = temp2;
                        } else {
                            temp = null;
                        }
                    }
                } else {
                    temp = null;
                }
            } else {
                temp = null;
            }
        }
        return posiblesMov2;
    }

    public HashMap<Integer, Casilla> getsaltosIzq(int tiposalto, int columnaux, int fila, Casilla temp, HashMap<Integer, Casilla> posiblesMov2) {
        Casilla temp2;
        int saltos = 1;
        while (temp != null) {
            System.out.println("-*-*-*#####**" + columnaux + "--" + fila);
            if ((temp2 = this.getCasillaIzq(columnaux, fila)) != null) {
                if (temp2.getTipoCasilla() == 0 || temp2.getTipoCasilla() == 1) {
                    int punteo = saltos * 4;
                    if (columnaux > 17 || columnaux < 8) {
                        punteo -= saltos * 2;
                    }
                    posiblesMovpunteo.add(new NodoHoja(punteo, temp2, columnaux, fila));
                    saltos++;
                    posiblesMov2.put(getClave(temp2), temp2);
                    columnaux -= 4;
                    if (columnaux < 0) {
                        columnaux = 0;
                        temp = null;
                        break;
                    } else {
                        if (Matriz[columnaux][fila].getTipoCasilla() > 1 && Matriz[columnaux][fila].getTipoCasilla() < 5) {
                            temp = temp2;
                        } else {
                            temp = null;
                        }
                    }
                } else {
                    temp = null;
                }
            } else {
                temp = null;
            }
        }
        return posiblesMov2;
    }

    /**
     * Devuelve la clave utilizada para identificar una casilla
     *
     * @param casilla Objeto al que se desea obtener la clave
     * @return Clave única para una casilla
     */
    public Integer getClave(Casilla casilla) {
        return casilla.getFila() * 100 + casilla.getColumna();
    }

    private Casilla getCasillaIzq(int columna, int fila) {
        if (columna - 2 >= 0) {
            return Matriz[columna - 2][fila];
        }
        return null;
    }

    private Casilla getCasillaDer(int columna, int fila) {
        if (columna + 2 < ancho) {
            return Matriz[columna + 2][fila];
        }
        return null;
    }

    private Casilla getCasillaIzqArriba(int columna, int fila) {
        if (columna - 1 >= 0 && fila - 1 >= 0) {
            return Matriz[columna - 1][fila - 1];
        }
        return null;
    }

    private Casilla getCasillaIzqAbajo(int columna, int fila) {
        if (columna - 1 >= 0 && fila + 1 < alto) {
            return Matriz[columna - 1][fila + 1];
        }
        return null;
    }

    private Casilla getCasillaDerArriba(int columna, int fila) {
        if (columna + 1 < ancho && fila - 1 >= 0) {
            return Matriz[columna + 1][fila - 1];
        }
        return null;
    }

    private Casilla getCasillaDerAbajo(int columna, int fila) {
        if (columna + 1 < ancho && fila + 1 < alto) {
            return Matriz[columna + 1][fila + 1];
        }
        return null;
    }
}
